package org.star.filters;

import io.netty.buffer.ByteBufAllocator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2024/1/4 11:46
 * @Description:
 */
@Slf4j
@Component
public class LogDecryptGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public int getOrder() {
        return 0;
    }

    /**
     * 后台打印日志：
     *      requestPath:/order-service-openfeign-nacos/getUserDetail
     *      queryParams:{name=[admin], city=[北京]}
     *      charBuffer:{
     * 	        "id":1,
     * 	        "name":"zhangsan丰",
     * 	        "age":18
     *      }
     *      bodyParam:{
     * 	        "id":1,
     * 	        "name":"zhangsan丰",
     * 	        "age":18
     *      }
     * @param exchange the current server exchange
     * @param chain provides a way to delegate to the next filter
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        // TODO 进行Content-type 与 method 判断
        StringBuffer sb = new StringBuffer();
        Flux<DataBuffer> body = exchange.getRequest().getBody();
        body.subscribe(buffer -> {
            // 解析body 数据
            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
            log.info("charBuffer:{}", charBuffer);
            // 在这里解密 并 重新塞进去
            sb.append(charBuffer);
        });
        //获取到最后的body 中的数据
        String bodyParam = sb.toString();
        log.info("bodyParam:{}", bodyParam);
        // TODO 这里进行业务操作
        //......

        //重新封装参数 向下传递
        DataBuffer bodyDataBuffer = stringBuffer(bodyParam);
        Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);
        request = new ServerHttpRequestDecorator(request) {
            @Override
            public Flux<DataBuffer> getBody() {
                return bodyFlux;
            }
        };
        // 封装我们的request
        return chain.filter(exchange.mutate().request(request).build());
    }

    protected DataBuffer stringBuffer(String value) {
        byte[] bytes = value.getBytes(StandardCharsets.UTF_8);

        NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
        DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
        buffer.write(bytes);
        return buffer;
    }


}
